package dxn.nl.file.center.netty.client;

import dxn.boot.common.config.CsApplicationContext;
import dxn.nl.file.biz.po.AppClientRegisterPo;
import dxn.nl.file.biz.service.AppClientRegisterBaseService;
import dxn.nl.file.center.CsCenterNettyConstants;
import dxn.nl.file.center.SocketManager;
import io.netty.channel.socket.SocketChannel;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.HashMap;

@Component
public class ClientSocketManager {
    private static final Logger logger = LoggerFactory.getLogger(ClientSocketManager.class);
    private static final HashMap<String, AppRegisterUtil> clientRegisterHashMap = new HashMap<>();

    private static AppClientRegisterBaseService appClientRegisterBaseService;
    public static int centPort = 0;

    public ClientSocketManager() {
    }

    public static boolean contains(String appId,String sessionId)
    {
        AppRegisterUtil appRegisterUtil = clientRegisterHashMap.get(appId);
        if(appRegisterUtil == null)
        {
            return false;
        }
        return appRegisterUtil.contains(sessionId);
    }

    private static AppClientRegisterBaseService getClientRegisterBaseService()
    {
        if(appClientRegisterBaseService == null)
        {
            appClientRegisterBaseService = CsApplicationContext.getBean(AppClientRegisterBaseService.class);
        }
        return appClientRegisterBaseService;
    }

    public static void addClient(String appId, String sessionId ,SocketChannel channel)
    {
        channel.attr(CsCenterNettyConstants.APP_ID).set(appId);
        channel.attr(CsCenterNettyConstants.APP_SESSION_ID).set(sessionId);

        AppRegisterUtil register = clientRegisterHashMap.get(appId);
        if(register == null)
        {
            register = new AppRegisterUtil();
            clientRegisterHashMap.put(appId,register);
        }

        register.add(sessionId,channel);

        try{
            AppClientRegisterBaseService registerBaseService = getClientRegisterBaseService();

            AppClientRegisterPo po = new AppClientRegisterPo();
            po.setAppId(appId);
            po.setSessionId(sessionId);
            po.setPort(channel.remoteAddress().getPort());
            po.setIp(channel.remoteAddress().getHostString());
            po.setRefreshTime(LocalDateTime.now());
            po.setRegisterTime(LocalDateTime.now());
            po.setCentIp(SocketManager.getIp());
            po.setCentPort(centPort);
            registerBaseService.saveAppClient(po);
        }
        catch (Exception ex)
        {
            logger.error("注册客户端db更新失败", ex);
        }
    }

    public static void removeClient(String appId,String sessionId)
    {
        AppRegisterUtil appRegisterUtil = clientRegisterHashMap.get(appId);
        if(appRegisterUtil != null)
        {
            appRegisterUtil.remove(sessionId);

            try{
                AppClientRegisterBaseService registerBaseService = getClientRegisterBaseService();
                registerBaseService.removeAppClient(appId,sessionId);
            }
            catch (Exception ex)
            {
                logger.error("", ex);
            }
        }
    }

    public static void refreshClient(String appId,String sessionId)
    {
        try{
            AppClientRegisterBaseService registerBaseService = getClientRegisterBaseService();
            registerBaseService.refreshAppClient(appId,sessionId,LocalDateTime.now());
        }
        catch (Exception ex)
        {
            logger.error("", ex);
        }
    }

    public static SocketChannel getClientChannel(String appId,String serverAddress)
    {
        if(StringUtils.isBlank(appId))
        {
            return null;
        }
        AppRegisterUtil register = clientRegisterHashMap.get(appId);
        if(register == null)
        {
            return null;
        }
        Pair<String,SocketChannel> pair = register.getDealChannel(serverAddress);
        if(pair.getRight()!=null && !pair.getRight().isActive())
        {
            register.remove(pair.getKey());
            try {
                pair.getRight().close();
            }
            catch (Exception ex)
            {
                logger.warn("",ex);
            }
            return getClientChannel(appId,serverAddress);
        }
        return pair.getRight();
    }
}
